package com.tdam2013.grupo07;

import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ListActivity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;

import com.tdam2013.grupo07.data.DatabaseHelper;
import com.tdam2013.grupo07.data.DatabaseHelperSingleton;
import com.tdam2013.grupo07.loader.ChatMensajeLoader;
import com.tdam2013.grupo07.mensajes.ChatMensaje;
import com.tdam2013.grupo07.networking.MessageDispatcherSingleton;
import com.tdam2013.grupo07.networking.MessageReciever;
import com.tdam2013.grupo07.networking.NetworkingSubscriber;
import com.tdam2013.grupo07.networking.SendMessageEventObserver;
import com.tdam2013.grupo07.networking.SendMessageResponse;
import com.tdam2013.grupo07.networking.ServerConectivity;
import com.tdam2013.grupo07.networking.ServerConectivitySingleton;
import com.tdam2013.grupo07.util.Constantes;

public class Chat extends ListActivity implements SendMessageEventObserver,
		NetworkingSubscriber, LoaderCallbacks<LinkedList<ChatMensaje>>,
		MessageReciever {

	// private NotificationHandler notificationHandler;
	private long contacto_id;
	private String contacto_nombre;
	private String contacto_usuario = "";

	private ImageButton ibEnviar;
	private EditText chatText;

	private ChatAdapter chatAdapter;

	private boolean banderaFinish = false;

	private View dialogView;
	private EditText editUsuario;
	private Button buttonOk;

	private final int CURSOR_USUARIO = 1; // Usuario de la consulta

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Eliminar la Title Bar
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_chat);

		Intent intent = this.getIntent();

		if (getIntent().getData() != null) {
			Cursor cursor = getContentResolver().query(getIntent().getData(),
					null, null, null, null);
			if (cursor != null && cursor.moveToNext()) {
				contacto_id = cursor.getLong(cursor
						.getColumnIndex(ContactsContract.Data.CONTACT_ID));
				contacto_nombre = cursor.getString(cursor
						.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
				cursor.close();
			}
		} else {
			contacto_id = intent.getLongExtra(Constantes.EXTRA_CONTACT_ID, -1);
			contacto_nombre = intent
					.getStringExtra(Constantes.EXTRA_CONTACT_NAME);
		}

		dialogView = (LayoutInflater.from(this)).inflate(
				R.layout.dialog_usuario_externo, null);
		editUsuario = (EditText) dialogView
				.findViewById(R.id.editUsuarioExterno);
		buttonOk = (Button) dialogView
				.findViewById(R.id.buttonOkUsuarioExterno);

		verificarUsuarioExterno();
		getLoaderManager().initLoader(0, null, this);

		chatAdapter = new ChatAdapter(this);
		setListAdapter(chatAdapter);
		registerForContextMenu(getListView());

		chatText = (EditText) findViewById(R.id.chatText);
		ibEnviar = (ImageButton) findViewById(R.id.enviarChat);

		ImageView imageContacto = (ImageView) findViewById(R.id.imageContacto);
		TextView nombreContacto = (TextView) findViewById(R.id.contactoNombreChat);
		ContentResolver cr = getContentResolver();
		String[] projection = new String[] { ContactsContract.Contacts._ID,
				ContactsContract.Contacts.PHOTO_THUMBNAIL_URI };
		final int CONTACT_PHOTO_THUMBNAIL_URI = 1;
		String selection = ContactsContract.Contacts._ID + " = ?";
		String[] selectionArgs = new String[] { String.valueOf(contacto_id) };
		String orden = ContactsContract.Contacts._ID + " ASC";
		Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI,
				projection, selection, selectionArgs, orden);

		if (cursor.moveToFirst()) {
			String toParse = cursor.getString(CONTACT_PHOTO_THUMBNAIL_URI);
			if (toParse != null) {
				Uri photo_uri = Uri.parse(toParse);
				imageContacto.setImageURI(photo_uri);
			} else {
				imageContacto.setImageDrawable(getResources().getDrawable(
						R.drawable.desconocido2));
			}
		}
		nombreContacto.setText(contacto_nombre);

		ibEnviar.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				String message = chatText.getText().toString().trim();
				if (!message.isEmpty()) {
					SharedPreferences preferences = PreferenceManager
							.getDefaultSharedPreferences(getApplicationContext());
					String sender = preferences.getString(
							Constantes.AJUSTES_USUARIO, null);
					String password = preferences.getString(
							Constantes.AJUSTES_PASSWD, null);
					ServerConectivity serverConectivity = ServerConectivitySingleton
							.getInstance(getApplicationContext())
							.getServerConectivity();
					serverConectivity.sendMessageAsync(sender, password,
							contacto_usuario, message);
				} else {
					Toast.makeText(getApplicationContext(),
							R.string.toast_mensaje_vacio_error,
							Toast.LENGTH_SHORT).show();
				}
			}
		});

	}

	private boolean verificarUsuarioExterno() {

		// @ASYNC
		DatabaseHelper dbHelper = DatabaseHelperSingleton.getInstance(
				getApplicationContext()).getDatabaseHelper();
		Cursor cursor = dbHelper.seleccionarContactoPorId(contacto_id);

		AlertDialog.Builder builder = new Builder(this);

		builder.setTitle(
				getResources().getString(
						R.string.generico_asignar_usuario_externo)).setView(
				dialogView);

		final AlertDialog dialog = builder.create();

		if (!cursor.moveToFirst() || cursor == null) {

			dialog.setOnKeyListener(new Dialog.OnKeyListener() {

				@Override
				public boolean onKey(DialogInterface arg0, int keyCode,
						KeyEvent event) {
					// Evito que se llame cuando es ACTION_UP
					if (event.getAction() != KeyEvent.ACTION_UP)
						return true;

					if (keyCode == KeyEvent.KEYCODE_BACK) {
						if (!banderaFinish) {
							Toast.makeText(
									getApplicationContext(),
									getResources()
											.getString(
													R.string.generico_mensaje_volver_contactos),
									Toast.LENGTH_SHORT).show();
							banderaFinish = true;
							return true;
						} else {
							dialog.dismiss();
							finish();
						}
					}
					banderaFinish = false;
					return true;
				}

			});

			buttonOk.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View view) {
					String username = editUsuario.getText().toString().trim();
					DatabaseHelper dbHelper = DatabaseHelperSingleton
							.getInstance(getApplicationContext())
							.getDatabaseHelper();
					dbHelper.insertarContacto7App(contacto_id, username);
					setContacto_usuario(username);
					AccountManager am = AccountManager
							.get(getApplicationContext());
					Account[] accounts = am
							.getAccountsByType(getString(R.string.ACCOUNT_TYPE));
					for (Account account : accounts) {
						ContentResolver.requestSync(account,
								"com.android.contacts", new Bundle());
					}
					dialog.dismiss();
				}
			});

			dialog.show();

		} else {
			contacto_usuario = cursor.getString(CURSOR_USUARIO);
		}
		return true;
	}

	@Override
	protected void onStart() {
		super.onStart();
		ServerConectivitySingleton.getInstance(this).getServerConectivity()
				.addSendMessageObserver(this);
		MessageDispatcherSingleton.getInstance().addMessageReciever(this);
	}

	@Override
	protected void onPause() {
		super.onPause();
		ServerConectivitySingleton.getInstance(this).getServerConectivity()
				.removeSendMessageObserver(this);
		MessageDispatcherSingleton.getInstance().removeMessageReciever(this);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.menu_chat, menu);
		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.ajustes:
			Intent ajustes = new Intent(this, Ajustes.class);
			this.startActivity(ajustes);
			return true;
		case R.id.historial_contacto:
			Intent historialC = new Intent(this, Historial.class);
			this.startActivity(historialC);
			return true;
		}
		return false;
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		menu.setHeaderTitle(getResources().getString(
				R.string.chat_menu_contextual_mensajes_titulo));
		menu.add(
				0,
				v.getId(),
				0,
				getResources().getString(
						R.string.chat_menu_contextual_accion_eliminar));
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		if (item.getTitle() == getResources().getString(
				R.string.chat_menu_contextual_accion_eliminar)) {
			AdapterContextMenuInfo menuInfoAdapter = (AdapterContextMenuInfo) item
					.getMenuInfo();
			DatabaseHelperSingleton.getInstance(this).getDatabaseHelper()
					.eliminarMensaje(menuInfoAdapter.id);
			chatAdapter.removeElementAt(menuInfoAdapter.position);
			Toast.makeText(
					this,
					getResources().getString(
							R.string.chat_menu_contextual_mensaje_eliminar),
					Toast.LENGTH_SHORT).show();
			return true;
		}
		return false;
	}

	public String getContacto_usuario() {
		return contacto_usuario;
	}

	public void setContacto_usuario(String contacto_usuario) {
		this.contacto_usuario = contacto_usuario;
	}

	@Override
	public void updateSendMessage(SendMessageResponse response) {
		if (response.getContact().equalsIgnoreCase(contacto_usuario)) {
			if (response.isSuccess()) {
				chatText.setText("");
				ChatMensaje mensaje = new ChatMensaje();
				mensaje.setId(response.getMessageId());
				mensaje.setTexto(response.getMessage());
				mensaje.setFecha(new Date(response.getDate()));
				mensaje.setDestinatario(response.getContact());
				mensaje.setTipo(ChatMensaje.TIPO_SALIENTE);
				chatAdapter.addLast(mensaje);
			} else {
				String message = "";
				switch (response.getErrorCode()) {
				case ServerConectivity.ERROR_NO_CONECTIVITY:
					message = getResources().getString(
							R.string.server_error_no_connectivity);
					break;

				case ServerConectivity.ERROR_USER_DOESNT_EXIST:
					message = getResources().getString(
							R.string.server_error_user_doesnt_exist);
					break;

				case ServerConectivity.ERROR_BAD_CREDENTIALS:
					message = getResources().getString(
							R.string.server_error_bad_credentials);
					break;

				default:
					message = getResources().getString(
							R.string.error_envio_mensaje_descripcion);
					break;
				}
				AlertDialog.Builder builder = new AlertDialog.Builder(this);
				builder.setTitle(R.string.error_envio_mensaje_titulo)
						.setMessage(message)
						.setPositiveButton(R.string.error_envio_mensaje_boton,
								null);
				AlertDialog dialog = builder.create();
				dialog.show();
			}
		}
	}

	@Override
	public Loader<LinkedList<ChatMensaje>> onCreateLoader(int id, Bundle args) {
		SharedPreferences preferences = PreferenceManager
				.getDefaultSharedPreferences(this);
		String usuario = preferences
				.getString(
						getResources().getString(
								R.string.activity_ajustes_usuario_key), null);
		String selection = String.format("%s = ? AND %s = ? ",
				DatabaseHelper.colContactoUsuario,
				DatabaseHelper.colContactoExterno);
		// @ASYNC
		DatabaseHelper dbHelper = DatabaseHelperSingleton.getInstance(
				getApplicationContext()).getDatabaseHelper();
		Cursor cursor = dbHelper.seleccionarContactoPorId(contacto_id);

		if (cursor.moveToFirst()) {
			contacto_usuario = cursor.getString(cursor
					.getColumnIndex(DatabaseHelper.colUsuario));
		}

		String[] selectionArgs = { usuario, contacto_usuario };
		return new ChatMensajeLoader(this, selection, selectionArgs,
				DatabaseHelper.colFecha + " ASC");

	}

	@Override
	public void onLoadFinished(Loader<LinkedList<ChatMensaje>> loader,
			LinkedList<ChatMensaje> mensajes) {
		chatAdapter.swapData(mensajes);
	}

	@Override
	public void onLoaderReset(Loader<LinkedList<ChatMensaje>> arg0) {
		chatAdapter.swapData(new LinkedList<ChatMensaje>());
	}

	@Override
	public void onReceiveMessage() {
		// TODO Auto-generated method stub
	}

	class ChatHolder {
		TextView txtChatFecha;
		TextView txtChatTexto;
	}

	class ChatAdapter extends BaseAdapter {

		private LinkedList<ChatMensaje> mensajes;
		private LayoutInflater inflater;

		// ItemMensaje (equivalente a Holder)
		class ItemMensaje {
			TextView fecha;
			TextView mensaje;
		}

		public ChatAdapter(Context context) {
			mensajes = new LinkedList<ChatMensaje>();
			inflater = LayoutInflater.from(context);
		}

		public void removeElementAt(int position) {
			mensajes.remove(position);
			this.notifyDataSetChanged();
		}

		@Override
		public int getCount() {
			return mensajes.size();
		}

		@Override
		public Object getItem(int position) {
			return mensajes.get(position);
		}

		@Override
		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return mensajes.get(position).getId();
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ChatHolder holder = null;
			if (convertView == null) {
				convertView = inflater.inflate(R.layout.item_mensaje, null);
				holder = new ChatHolder();
				holder.txtChatFecha = (TextView) convertView
						.findViewById(R.id.chat_fecha);
				holder.txtChatTexto = (TextView) convertView
						.findViewById(R.id.chat_texto);
				convertView.setTag(holder);
			} else {
				holder = (ChatHolder) convertView.getTag();
			}

			ChatMensaje mensaje = mensajes.get(position);
			SimpleDateFormat format = new SimpleDateFormat(getResources()
					.getString(R.string.date_time_format));
			holder.txtChatFecha.setText(format.format(mensaje.getFecha()));
			holder.txtChatTexto.setText(mensaje.getTexto());
			if (mensaje.getTipo() == ChatMensaje.TIPO_ENTRANTE) {
				LinearLayout.LayoutParams para=new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT );
				para.setMargins(0, 10, 0, 10); //left,top,right, bottom
				para.gravity=Gravity.LEFT;
				holder.txtChatFecha.setLayoutParams(para);
				holder.txtChatTexto.setLayoutParams(para);
				holder.txtChatTexto
						.setBackgroundResource(R.drawable.bubble_yellow);
			} else {
				LinearLayout.LayoutParams para=new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT );
				para.setMargins(0, 10, 0, 10); //left,top,right, bottom
				para.gravity=Gravity.RIGHT;
				holder.txtChatFecha.setLayoutParams(para);
				holder.txtChatTexto.setLayoutParams(para);
				holder.txtChatTexto
						.setBackgroundResource(R.drawable.bubble_green);
			}
			return convertView;
		}

		public void addLast(ChatMensaje mensaje) {
			mensajes.addLast(mensaje);
			this.notifyDataSetChanged();
		}

		public void swapData(LinkedList<ChatMensaje> mensajes) {
			this.mensajes = mensajes;
			this.notifyDataSetChanged();
		}

		public void addAllLast(List<ChatMensaje> messages) {
			for (ChatMensaje message : messages) {
				addLast(message);
			}
		}
	}

	@Override
	public void onMessageRecieved(List<ChatMensaje> messages) {
		Collections.sort(messages);
		for (ChatMensaje message : messages) {
			if (message.getDestinatario().equalsIgnoreCase(contacto_usuario)) {
				chatAdapter.addLast(message);
			}
		}

	}
}
